package com.kun.companion.core.thread;

import cn.hutool.core.util.StrUtil;
import com.kun.companion.core.context.DestroyingBean;
import com.kun.companion.core.exception.Assert;
import com.kun.companion.core.util.ComUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.*;
import java.util.function.Supplier;

/**
 * TODO
 *
 * @author gzc
 * @since 2025/2/7 19:32
 **/
public abstract class AbstractThreadPool implements DestroyingBean {
    private static final Logger log = LoggerFactory.getLogger(AbstractThreadPool.class);

    protected final ThreadPoolExecutor pool;

    protected AbstractThreadPool(ThreadPoolExecutor pool) {
        this.pool = Assert.notNull(pool, "线程池为空");
    }

    protected AbstractThreadPool() {
        this.pool = Assert.notNull(createPool(), "线程池创建失败, createPool()返回null");
    }

    public <T> Future<T> submit(Callable<T> task) {
        FutureTask<T> futureTask = new FutureTask<>(task);
        execute(futureTask);
        return futureTask;
    }

    public Future<?> submit(Runnable task) {
        return pool.submit(task);
    }

    public Future<?> submitUI(Runnable task) {
        return submit(() -> ComUtil.uiThreadRun(task));
    }

    public void execute(Runnable task) {
        pool.execute(task);
    }

    public void executeUI(Runnable task) {
        execute(() -> ComUtil.uiThreadRun(task));
    }

    public CompletableFuture<Void> runAsync(Runnable runnable) {
        return CompletableFuture.runAsync(runnable, pool);
    }

    public CompletableFuture<Void> runAsyncUI(Runnable runnable) {
        return runAsync(() -> ComUtil.uiThreadRun(runnable));
    }

    public <T> CompletableFuture<T> supplyAsyncCallable(Callable<T> callable) {
        return supplyAsync(() -> {
            try {
                return callable.call();
            } catch (Exception e) {
                throw new CompletionException(e);
            }
        });
    }

    public <T> CompletableFuture<T> supplyAsync(Supplier<T> supplier) {
        return CompletableFuture.supplyAsync(supplier, pool);
    }

    public <T> CompletableFuture<T> supplyAsyncUI(Supplier<T> supplier) {
        return supplyAsync(() -> {
            CompletableFuture<T> future = new CompletableFuture<>();
            ComUtil.uiThreadRun(() -> {
                try {
                    future.complete(supplier.get());
                } catch (Exception e) {
                    future.completeExceptionally(e);
                }
            });
            // 阻塞当前线程直到UI线程完成
            return future.join();
        });
    }

    public ThreadPoolExecutor getPool() {
        return this.pool;
    }

    /**
     * 子类必须实现此方法并返回非空的ThreadPoolExecutor实例
     *
     * @return 线程池对象
     */
    protected abstract ThreadPoolExecutor createPool();

    @Override
    public String toString() {
        String state = pool.isTerminated() ? "已终止" :
                pool.isShutdown() ? "关闭中" : "运行中";
        String queueType = pool.getQueue().getClass().getSimpleName();
        String param = "状态={}, 核心线程数={}, 最大线程数={}, 活跃线程数={}, 总任务数={}, 完成数={}, 队列大小={}, 队列类型={}";
        return StrUtil.format(param, state,
                pool.getCorePoolSize(), pool.getMaximumPoolSize(),
                pool.getActiveCount(), pool.getTaskCount(),
                pool.getCompletedTaskCount(), pool.getQueue().size(), queueType);
    }

    @Override
    public void destroy() {
        // 1. 停止接受新任务
        pool.shutdown();
        try {
            // 2. 等待现有任务完成
            if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
                log.warn("线程池未及时关闭，剩余任务数: {}", pool.getQueue().size());
                // 3. 尝试取消未执行任务
                List<Runnable> droppedTasks = pool.shutdownNow();
                log.warn("强制关闭，丢弃任务数: {}", droppedTasks.size());
                // 4. 调用扩展点供子类处理
                onTasksDropped(droppedTasks);
            }
        } catch (InterruptedException e) {
            log.warn("线程池关闭被中断", e);
            pool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    protected void onTasksDropped(List<Runnable> droppedTasks) {
        // 子类可重写以处理未完成任务
    }
}
